package com.zmn.oms.zmn.aop;

import com.alibaba.fastjson.JSON;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.oms.business.interfaces.conf.distributereason.ConfOrderDistributeReasonBService;
import com.zmn.oms.business.interfaces.log.OrderRedistributeLogBService;
import com.zmn.oms.common.annotation.OrderWorkRedistributeLog;
import com.zmn.oms.common.constant.AppConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.constant.OrderWorkRedistributeLogConsts;
import com.zmn.oms.common.dto.OrderWorkRedistributeOperator;
import com.zmn.oms.common.enums.RedistributeStatusEnum;
import com.zmn.oms.model.bo.work.redistribute.OrderWorkRedistributeModifyBO;
import com.zmn.oms.model.entity.log.OrderRedistributeLog;
import com.zmn.oms.model.entity.redistribute.OrderWorkRedistributeApply;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.redistribute.OrderWorkRedistributeApplyService;
import com.zmn.oms.services.interfaces.redistribute.OrderWorkRedistributeInfoService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.util.Objects;
import java.util.Optional;


/**
 * @author sunlife
 * @date:2022/5/13 下午7:02
 * description: 工单改派日志切面
 */
@Aspect
@Configuration
@Order(-2)
@Slf4j
public class OrderWorkRedistributeLogAspect {
    @Autowired
    OrderRedistributeLogBService orderRedistributeLogBService;
    @Autowired
    OrderWorkService orderWorkService;
    @Autowired
    OrderWorkRedistributeApplyService orderWorkRedistributeApplyService;
    @Autowired
    OrderWorkRedistributeInfoService orderWorkRedistributeInfoService;
    @Autowired
    ConfOrderDistributeReasonBService confOrderDistributeReasonBService;

    /**
     * 设定切入点
     */
    @Pointcut("@annotation(com.zmn.oms.common.annotation.OrderWorkRedistributeLog)")
    private void orderPointCut() {
    }

    @Around("orderPointCut() && @annotation(orderWorkRedistributeLog)")
    public Object orderDoAfter(ProceedingJoinPoint joinPoint, OrderWorkRedistributeLog orderWorkRedistributeLog) throws Throwable {

        Long orderId = null;
        Long redistributeId = null;
        if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
            if (joinPoint.getArgs()[0] instanceof OrderWorkRedistributeOperator) {
                OrderWorkRedistributeOperator operator = (OrderWorkRedistributeOperator) joinPoint.getArgs()[0];
                orderId = operator.getOrderId();
                redistributeId = operator.getRedistributeId();
            }
        }
        // 操作类型
        int logType = orderWorkRedistributeLog.type();
        boolean beforeProceed = orderWorkRedistributeLog.beforeProceed();
        log.info("aop#改派日志--->orderId:{} -- redistributeId:{} --> logType:{}", orderId, redistributeId, logType);
        return this.doLog(joinPoint, logType, beforeProceed);
    }

    Object doLog(ProceedingJoinPoint joinPoint, int logType, boolean beforeProceed) throws Throwable {

        // 改派操作参数
        OrderWorkRedistributeOperator orderWorkRedistributeOperator = (OrderWorkRedistributeOperator) joinPoint.getArgs()[0];
        log.debug("改派操作参数:{}", JSON.toJSONString(orderWorkRedistributeOperator));

        // 工单log
        OrderRedistributeLog orderLog = new OrderRedistributeLog();
        orderLog.setType(logType);
        orderLog.setTypeName(OrderWorkRedistributeLogConsts.getLogTypeNameByType((logType)));

        OrderWorkRedistributeApply orderWorkRedistributeApply = null;
        Object proceed = null;
        if (beforeProceed) {
            // 查询改派申请信息
            orderLog.setRedistributeId(orderWorkRedistributeOperator.getRedistributeId());
            if (Objects.nonNull(orderWorkRedistributeOperator) && NumberUtil.isNotNullOrZero(orderWorkRedistributeOperator.getRedistributeId())) {
                orderWorkRedistributeApply = orderWorkRedistributeApplyService.selectByKeySrcMaster(orderWorkRedistributeOperator.getRedistributeId());
            }
            // 修改订单，获取日志
            orderLog.setContent(this.getLogContent(orderWorkRedistributeApply, orderWorkRedistributeOperator, orderLog));

            // 后执行
            proceed = joinPoint.proceed();

        } else {
            // 先执行
            proceed = joinPoint.proceed();

            // 查询改派申请信息
            orderLog.setRedistributeId(orderWorkRedistributeOperator.getRedistributeId());
            if (Objects.nonNull(orderWorkRedistributeOperator) && NumberUtil.isNotNullOrZero(orderWorkRedistributeOperator.getRedistributeId())) {
                orderWorkRedistributeApply = orderWorkRedistributeApplyService.selectByKeySrcMaster(orderWorkRedistributeOperator.getRedistributeId());
            }

            // 修改订单，获取日志
            orderLog.setContent(this.getLogContent(orderWorkRedistributeApply, orderWorkRedistributeOperator, orderLog));
        }

        // 工单状态处理
        orderLog.setOrderId(orderWorkRedistributeApply.getOrderId());
        orderLog.setWorkId(orderWorkRedistributeApply.getWorkId());
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderWorkRedistributeApply.getOrderId(), orderWorkRedistributeApply.getWorkId());
        this.processOrderLogStatus(orderLog, dbOrderWork, orderWorkRedistributeOperator);
        // 操作人处理
        this.processOrderRedistributeLogOperater(orderLog, orderWorkRedistributeOperator, orderWorkRedistributeApply);

        // 插入日志
        orderRedistributeLogBService.save(orderLog);

        // 节点异步通知绩效系统
        this.nodeNotice(orderLog, orderWorkRedistributeApply);

        // 改派节点异步日志通知
        this.notice(orderLog, orderWorkRedistributeOperator, orderWorkRedistributeApply);

        return proceed;
    }

    /**
     * 改派节点通知
     * @param orderLog
     * @param orderWorkRedistributeOperator
     * @param orderWorkRedistributeApply
     */
    private void notice(OrderRedistributeLog orderLog, OrderWorkRedistributeOperator orderWorkRedistributeOperator, OrderWorkRedistributeApply orderWorkRedistributeApply) {
        orderRedistributeLogBService.notice(orderLog,orderWorkRedistributeOperator, orderWorkRedistributeApply);
    }

    /**
     *  工单状态处理
     * @param orderLog
     * @param dbOrderWork
     * @param orderWorkRedistributeOperator
     */
    private void processOrderLogStatus(OrderRedistributeLog orderLog, OrderWork dbOrderWork, OrderWorkRedistributeOperator orderWorkRedistributeOperator) {
        if (Objects.isNull(dbOrderWork)) {
            return;
        }
        // 订单Id 工单Id
        orderLog.setOrderId(orderWorkRedistributeOperator.getOrderId());
        orderLog.setWorkId(orderWorkRedistributeOperator.getWorkId());

        // 操作经纬度
        orderLog.setLatitude(orderWorkRedistributeOperator.getLatitude());
        orderLog.setLongitude(orderWorkRedistributeOperator.getLongitude());

        // 操作前状态结果
        Integer status = dbOrderWork.getStatus();
        Integer resultStatus = dbOrderWork.getResultStatus();

        String orderStatusName = OrderStatusConsts.getWorkStatusName(status);
        String orderResultStatusName = OrderStatusConsts.getWorkResultStatusName(resultStatus);
        orderLog.setBeforeStatus(status);
        orderLog.setBeforeStatusName(orderStatusName);
        orderLog.setBeforeResultStatus(resultStatus);
        orderLog.setBeforeResultStatusName(orderResultStatusName);

        orderLog.setAfterStatus(status);
        orderLog.setAfterStatusName(orderStatusName);
        orderLog.setAfterResultStatus(resultStatus);
        orderLog.setAfterResultStatusName(orderResultStatusName);
    }

    /**
     * 工单改派节点通知绩效系统
     *
     * @param orderLog
     * @param orderWorkRedistributeApply
     */
    private void nodeNotice(OrderRedistributeLog orderLog, OrderWorkRedistributeApply orderWorkRedistributeApply) {
        try {
            orderRedistributeLogBService.nodeNotice(orderLog, orderWorkRedistributeApply);
        } catch (Exception e) {
            log.error("工单改派日志-异步推送消息异常：{}", e);
        }
    }

    /**
     * 工单改派操作人处理
     *
     * @param orderLog
     * @param operator
     * @param orderWorkRedistributeApply
     */
    private void processOrderRedistributeLogOperater(OrderRedistributeLog orderLog, OrderWorkRedistributeOperator operator, OrderWorkRedistributeApply orderWorkRedistributeApply) {
        if (operator == null) {
            // 系统
            orderLog.setOperator("系统");
            orderLog.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            orderLog.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        } else {
            if (Objects.equals(operator.getOperatorType(), 0)) {
                operator.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                operator.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            }
            int operatorType = Optional.ofNullable(operator.getOperatorType()).orElse(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            orderLog.setOperator(Optional.ofNullable(operator.getOperator()).orElse(GlobalConsts.getOperatorTypeName(operatorType)));
            if (Objects.equals(GlobalConsts.OPERATE_USER_TYPE_USER, operatorType) && StringUtil.isMobile(operator.getOperator())) {
                orderLog.setOperator(StringUtil.formatHideMobile(operator.getOperator()));
            }
            orderLog.setOperatorId(Optional.ofNullable(operator.getOperatorId()).orElse((long) operatorType));
            orderLog.setOperatorType(operatorType);
            orderLog.setCreateTime(operator.getOperateTime());
        }
    }

    /**
     * 组装日志内容
     *
     * @param orderWorkRedistributeApply
     * @param orderWorkRedistributeOperator
     * @param orderRedistributeLog
     * @return
     */
    private String getLogContent(OrderWorkRedistributeApply orderWorkRedistributeApply, OrderWorkRedistributeOperator orderWorkRedistributeOperator, OrderRedistributeLog orderRedistributeLog) {
        String content = "";
        switch (orderRedistributeLog.getType()) {
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_ADD_APPLY:
                content = orderWorkRedistributeOperator.getRedistributeOperatorLogRemark();
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_START_AUDIT:
                content = orderWorkRedistributeOperator.getRedistributeOperatorLogRemark();
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_AUDIT:
                content = orderWorkRedistributeOperator.getRedistributeOperatorLogRemark();
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_HELP_TAKE:
                content = this.getAppBaseLogContent(orderWorkRedistributeOperator);
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_REDISTRIBUTE:
                content = orderWorkRedistributeOperator.getRedistributeOperatorLogRemark();
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_REDISTRIBUTE_SYSTEM:
                content = orderWorkRedistributeOperator.getRedistributeOperatorLogRemark();
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_CANCEL:
                if (Objects.equals(orderWorkRedistributeOperator.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_SYSTEM)) {
                    content = orderWorkRedistributeOperator.getRedistributeOperatorLogRemark();
                } else {
                    content = this.getAppBaseLogContent(orderWorkRedistributeOperator);
                }
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_ADD_EXCEPTION:
                content = this.getRedistributeAddExceptionLogContent(orderWorkRedistributeOperator, orderWorkRedistributeApply);
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_REDISTRIBUTE_REJECT:
                content = this.getRedistributeRejectLogContent(orderWorkRedistributeOperator, orderWorkRedistributeApply);
                break;
            case OrderWorkRedistributeLogConsts.ORDER_REDISTRIBUTE_LOG_TYPE_ADD_NOTE:
                content = this.getAddRemarkLogContent(orderWorkRedistributeOperator, orderWorkRedistributeApply);
                break;
            default:
                content = "未知日志类型";
        }

        return content;
    }

    /**
     * 获取录入备注日志内容
     * @param orderWorkRedistributeOperator
     * @param orderWorkRedistributeApply
     * @return
     */
    private String getAddRemarkLogContent(OrderWorkRedistributeOperator orderWorkRedistributeOperator, OrderWorkRedistributeApply orderWorkRedistributeApply) {
        OrderWorkRedistributeModifyBO modifyBO = (OrderWorkRedistributeModifyBO) orderWorkRedistributeOperator;
        return modifyBO.getLastRemark();
    }

    /**
     * 获取改派虚假异常日志内容
     * @param orderWorkRedistributeOperator
     * @param orderWorkRedistributeApply
     * @return
     */
    private String getRedistributeAddExceptionLogContent(OrderWorkRedistributeOperator orderWorkRedistributeOperator, OrderWorkRedistributeApply orderWorkRedistributeApply) {
        StringBuilder sb = new StringBuilder();
        sb.append("异常类型：工程师异常 - 虚假 - 虚假改派");
        sb.append("\n异常对象：" + orderWorkRedistributeApply.getApplyUser());
        return sb.toString();
    }

    /**
     * 获取改派驳回日志内容
     * @param orderWorkRedistributeOperator
     * @param orderWorkRedistributeApply
     * @return
     */
    private String getRedistributeRejectLogContent(OrderWorkRedistributeOperator orderWorkRedistributeOperator, OrderWorkRedistributeApply orderWorkRedistributeApply) {
        StringBuilder logContent = new StringBuilder();
        logContent.append("改派状态：");
        logContent.append(RedistributeStatusEnum.CANCEL_REDISTRIBUTE.getDesc());
        logContent.append("\n");
        logContent.append("备注：系统自动驳回改派");
        return logContent.toString();
    }

    /**
     * app基础信息
     *
     * @param orderWorkRedistributeOperator
     * @return
     */
    private String getAppBaseLogContent(OrderWorkRedistributeOperator orderWorkRedistributeOperator) {
        StringBuilder sb = new StringBuilder();
        if (orderWorkRedistributeOperator.getAppPlat() != null) {
            sb.append("app系统：");

            switch (orderWorkRedistributeOperator.getAppPlat()) {
                case AppConsts.APP_OS_ANDROID: {
                    sb.append("Android");
                    break;
                }
                case AppConsts.APP_OS_IOS: {
                    sb.append("IOS");
                    break;
                }
                default: {
                    sb.append(orderWorkRedistributeOperator.getAppPlat());
                    break;
                }
            }
            sb.append("\n版本号：V ");
            sb.append(orderWorkRedistributeOperator.getDisplayVersion());
        }
        return sb.toString();
    }
}
